use serde_json::Value;

use crate::{
  input::{Opts, OptsApi},
  ty::drive::DriveStatusType,
};

/// # Input api 统一接口
///
/// # Rust
///```rust
/// use e_app::input::api;
/// use e_app::input::drive_init;
/// use e_app::input::Opts;
/// use e_utils::cmd::CmdResult;
/// use serde_json::Value;
/// #[tokio::main]
/// async fn main() -> e_utils::AnyResult<()> {
///   let opts = Opts::new(None as Option<Vec<&str>>)?;
///   if opts.init {
///     drive_init()?;
///   }
///   let mut res: CmdResult<Value> = CmdResult {
///     content: String::new(),
///     status: false,
///     opts: Value::Null,
///   };
///   match api(opts).await {
///     Ok(v) => {
///       res.content = v;
///       res.status = true;
///     }
///     Err(e) => res.content = e.to_string(),
///   }
///   println!("{}", res.to_string_pretty()?);
///   Ok(())
/// }
/// ```
pub async fn api(op: Opts, _opts: &mut Value) -> e_utils::AnyResult<String> {
  match op.api {
    OptsApi::Fileinfo => {
      #[cfg(feature = "fileinfo")]
      {
        let args = op.args.get(0).ok_or("Args Error must > 0 ")?;
        return match &*op.task {
          "all" => crate::ty::fileinfo::all(args),
          "copy-lib" => {
            let to = op.args.get(1).ok_or("Args Error must > 1 ")?;
            Ok(crate::ty::fileinfo::lib_copy(args, to).map(|v| format!("Copy count {}", v))?)
          }
          "print" => Ok(serde_json::to_string_pretty(&crate::ty::fileinfo::open(args)?)?),
          _ => Err("Task Error".into()),
        };
      }
    }
    OptsApi::None => return Err("Api cannot eq None".into()),
    OptsApi::Active => {
      #[cfg(feature = "os-active")]
      {
        return match &*op.task {
          "check" => crate::os_active::check_os_active(),
          "active" => {
            let args = op.command.get(0).ok_or("Command Error must > 1 ")?;
            let args2 = op.command.get(1).ok_or("Command Error must > 1 ")?.clone();
            let temp_type = crate::os_active::ActiveLocalType::Temp(args2);
            crate::os_active::active_os(&args, temp_type)
          }
          "deactive" => crate::os_active::deactivate_os(),
          "rkms" => {
            let args = op.command.get(0).ok_or("Command Error must > 0 ")?;
            crate::os_active::register_kms(args)
          }
          "ckms" => crate::os_active::clear_kms(),
          "clean-cache" => {
            let args = op.command.get(0).ok_or("Command Error must > 0 ")?.clone();
            Ok(crate::os_active::clean_cache(crate::os_active::ActiveLocalType::Temp(args))?)
          }
          "query-cache" => {
            let args = op.command.get(0).ok_or("Command Error must > 0 ")?.clone();
            crate::os_active::query_cache(crate::os_active::ActiveLocalType::Temp(args))
          }
          _ => Err("Task Error".into()),
        };
      }
    }
    OptsApi::Office => {
      return match &*op.task {
        // "check" => m_opts(check_office(), opts),
        // "rkms" => {
        //     if op.command.len() > 0 {
        //         m_opts(register_office_kms(&op.command[0]), opts)
        //     } else {
        //         return Err("Command Error must > 0 ".into());
        //     }
        // }
        _ => Err("Task Error".into()),
      };
    }
    OptsApi::Clean => {
      #[cfg(feature = "clean")]
      {
        return match &*op.task {
          "empty-recycle-bin" => crate::clean::empty_recycle_bin(),
          "empty-access-log" => crate::clean::empty_access_log(),
          "empty-netshare" => crate::clean::empty_netshare("*"),
          // 待校验
          "empty-activity-history" => crate::clean::empty_activity_history(),
          // 待校验
          "empty-run-history" => crate::clean::empty_run_history(),
          _ => Err("Task Error".into()),
        };
      }
    }
    OptsApi::Drive => {
      #[cfg(feature = "drive")]
      {
        return match &*op.task {
          "scan" => crate::drive::pnputil_scan(),
          "add-file" => {
            let args: Vec<&str> = op.args.iter().map(|x| x.as_ref()).collect();
            let mut outres = String::new();
            for x in e_utils::fs::tree_folder(&args[0])?
              .into_iter()
              .filter(|x| std::path::Path::new(x).extension().unwrap_or_default() == "inf")
            {
              let mut new_args = args.clone();
              if let Some(v) = new_args.get_mut(0) {
                *v = x.as_os_str().to_str().unwrap_or_default();
              }
              let res = crate::drive::pnputil_add_driver(new_args)?;
              outres += &format!("{:?};;", res);
            }
            Ok(outres)
          }
          "add" => {
            let args: Vec<&str> = op.args.iter().map(|x| x.as_ref()).collect();
            let res = crate::drive::pnputil_add_driver(args)?;
            // 待优化判断添加驱动
            Ok(res)
          }
          "delete" => {
            let args = op.args.clone();
            Ok(crate::drive::pnputil_delete_driver(args)?)
          }
          "delete-find" => {
            let commands = op.command.iter().map(|x| x.as_ref()).collect::<Vec<&str>>();
            let devcon_node_list = crate::drive::findnodes(&op, commands)?;
            let args_src = op.args.clone();
            let mut nodes = vec![];
            for node in &devcon_node_list {
              let inf_path: std::path::PathBuf = (&node.inf_file).into();
              let fname = inf_path.file_name().and_then(|v| v.to_str()).ok_or("File name error")?;
              let mut args = args_src.clone();
              args.insert(0, fname.to_string());
              let _dres = crate::drive::pnputil_delete_driver(args)?;
              let status = crate::drive::devcon_status(&node.id)?;
              if status.status != DriveStatusType::None {
                return Err("Delete Error: not null".into());
              }
              nodes.push(node)
            }
            Ok(serde_json::to_string_pretty(&nodes)?)
          }
          "print" => {
            let commands = op.command.iter().map(|x| x.as_ref()).collect::<Vec<&str>>();
            let devcon_node_list = crate::drive::findnodes(&op, commands)?;
            for node in &devcon_node_list {
              println!("{}", serde_json::to_string_pretty(&node)?);
            }
            Ok(String::from("PASS"))
          }
          "findnodes" => {
            let commands = op.command.iter().map(|x| x.as_ref()).collect::<Vec<&str>>();
            let devcon_node_list = crate::drive::findnodes(&op, commands)?;
            Ok(serde_json::to_string_pretty(&devcon_node_list)?)
          }
          "restart" => {
            let mut res = crate::share::default_cmd_res();
            let status_list = crate::drive::find_with_run(&op, crate::drive::pnputil_restart)?;
            for status in &status_list {
              if status.status == DriveStatusType::Runing {
                res.status = true;
                break;
              }
            }
            Ok(serde_json::to_string_pretty(&status_list)?)
          }
          "enable" => {
            let status_list = crate::drive::find_with_run(&op, crate::drive::pnputil_enable)?;
            for status in &status_list {
              if status.status != DriveStatusType::Runing {
                return Err("Enable Error: not runing".into());
              }
            }
            Ok(serde_json::to_string_pretty(&status_list)?)
          }
          "disable" => {
            let status_list = crate::drive::find_with_run(&op, crate::drive::pnputil_disable)?;
            for status in &status_list {
              if status.status != DriveStatusType::Disabled {
                return Err("Disable Error: not disabled".into());
              }
            }
            Ok(serde_json::to_string_pretty(&status_list)?)
          }
          "remove" => {
            let status_list = crate::drive::find_with_run(&op, crate::drive::pnputil_remove)?;
            for status in &status_list {
              if status.status != DriveStatusType::None {
                return Err("Remove Error: not none".into());
              }
            }
            Ok(serde_json::to_string_pretty(&status_list)?)
          }
          "export" => {
            let args_src: Vec<&str> = op.args.iter().map(|x| x.as_ref()).collect();
            Ok(crate::drive::pnputil_export_driver(args_src)?)
          }
          _ => {
            let args = op.command.clone();
            crate::drive::devcon(args)
          }
        };
      }
    }
    OptsApi::DesktopInfo => {
      #[cfg(feature = "desktop-info")]
      {
        let attr_filter = op.args.get(0).and_then(|v| v.parse::<u32>().ok()).filter(|&v| v > 0);
        let query_user = op.args.get(1).cloned();
        let filters = op.command.clone();
        return match &*op.task {
          "print" => {
            let mut items = crate::desktop_info::get_desktop_items(query_user, attr_filter, &filters);
            items.dedup_by_key(|v| v.path.clone());
            for item in items {
              let is_dir = if item.is_dir { "目录" } else { "" };
              let is_hidden = if item.is_hidden { "隐藏" } else { "" };
              println!(
                "[{}] 用户[{}] 属性[{}] {} {}",
                item.path.display(),
                item.uname,
                item.attribute,
                is_dir,
                is_hidden
              );
            }
            Ok(String::from("PASS"))
          }
          "all" => {
            let mut items = crate::desktop_info::get_desktop_items(query_user, attr_filter, &filters);
            items.dedup_by_key(|v| v.path.clone());
            Ok(serde_json::to_string_pretty(&items)?)
          }
          _ => Err("Task Error".into()),
        };
      }
    }
    OptsApi::DiskInfo => {
      #[cfg(feature = "disk-info")]
      {
        return match &*op.task {
          // "all" => Ok(serde_json::to_string_pretty(
          //   &crate::disk_info::get_logical_drives(),
          // )?),
          // "print" => {
          //   let drives = crate::disk_info::get_logical_drives();
          //   for drive in drives {
          //     println!("{}", serde_json::to_string_pretty(&drive)?)
          //   }
          //   Ok(String::from("PASS"))
          // }
          _ => Err("Task Error".into()),
        };
      }
    }
  }
  #[allow(unused)]
  Err("Api Error".into())
}
